<script setup name="leftViews">
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import {
	ternaryDatabase,
	binaryDatabase,
	elementOptions,
	formConfig,
	validators,
	getAllElementsBinary,
	getAllElementsTernary,
	getSecondElementsBinaryUniversal,
	getSecondElementsTernaryUniversal,
	getThirdElementsTernaryUniversal,
} from '../utils/config.js'

const props = defineProps({
	isLoading: Boolean,
	type: String, // 'binary' 或 'ternary'
})

const emit = defineEmits(['on-submit'])

const formRef = ref(null)

// 根据类型决定使用二元还是三元的表单字段
const isBinary = computed(() => props.type === 'binary')

// 表单数据
const form = ref({
	// 通用字段
	firstElement: '',
	secondElement: '',
	thirdElement: '', // 仅三元使用
	pressure: 101325,
	temperature: 600,

	// 主动改变元素
	comp1: '', // 用户选择的元素1
	comp1_value: 0.4, // 元素1成分值
	comp2: '', // 用户选择的元素2
	comp2_value: 0.3, // 元素2成分值
	comp3: '', // 自动计算的元素3（仅三元使用）
	comp3_value: 0.3, // 元素3成分值（仅三元使用）

	// 单位
	comp1_unit: '摩尔分数',
	comp2_unit: '摩尔分数',
	comp3_unit: '摩尔分数',
})

// 计算属性 - 当前TDB文件
const currentTdbFile = computed(() => {
	if (isBinary.value) {
		if (!form.value.firstElement || !form.value.secondElement) return ''
		const matched = binaryDatabase.getMatchedCombination([
			form.value.firstElement,
			form.value.secondElement,
		])
		return matched?.dbFile || ''
	} else {
		if (
			!form.value.firstElement ||
			!form.value.secondElement ||
			!form.value.thirdElement
		)
			return ''
		const matched = ternaryDatabase.getMatchedConfiguration([
			form.value.firstElement,
			form.value.secondElement,
			form.value.thirdElement,
		])
		return matched?.dbFile || ''
	}
})

// 验证规则
const validationRules = computed(() => {
	const baseRules = {
		firstElement: [validators.required('请选择第一个元素')],
		secondElement: [validators.required('请选择第二个元素')],
		pressure: [validators.positiveNumber('压强必须大于等于0')],
		temperature: [validators.positiveNumber('温度必须大于等于0')],
		comp1: [validators.required('请选择元素1')],
		comp1_value: [validators.range01('元素1成分值必须在0到1之间')],
	}

	if (isBinary.value) {
		return {
			...baseRules,
			comp1_value: [
				...baseRules.comp1_value,
				{
					validator: (_, value, callback) => {
						if (value > 1) {
							callback(new Error('元素1成分值必须小于1'))
						} else {
							callback()
						}
					},
					trigger: 'blur',
				},
			],
		}
	} else {
		return {
			...baseRules,
			thirdElement: [validators.required('请选择第三个元素')],
			comp2: [validators.required('请选择元素2')],
			comp1_value: [
				...baseRules.comp1_value,
				{
					validator: (_, value, callback) => {
						const sum = value + form.value.comp2_value
						if (sum > 1) {
							callback(new Error('元素1和元素2成分值之和不能超过1'))
						} else {
							callback()
						}
					},
					trigger: 'blur',
				},
			],
			comp2_value: [
				validators.range01('元素2成分值必须在0到1之间'),
				{
					validator: (_, value, callback) => {
						const sum = form.value.comp1_value + value
						if (sum > 1) {
							callback(new Error('元素1和元素2成分值之和不能超过1'))
						} else {
							callback()
						}
					},
					trigger: 'blur',
				},
			],
		}
	}
})

// 计算属性 - 可选元素
const allElements = computed(() =>
	isBinary.value ? getAllElementsBinary() : getAllElementsTernary()
)
const availableSecondElements = computed(() =>
	isBinary.value
		? getSecondElementsBinaryUniversal(form.value.firstElement)
		: getSecondElementsTernaryUniversal(form.value.firstElement)
)
const availableThirdElements = computed(() =>
	getThirdElementsTernaryUniversal(
		form.value.firstElement,
		form.value.secondElement
	)
)

// 二元相图可选元素
const binaryElements = computed(() => {
	if (!form.value.firstElement || !form.value.secondElement) return []
	return [form.value.firstElement, form.value.secondElement]
})
const availableComp1Elements = computed(() => binaryElements.value)
const remainingBinaryElement = computed(() => {
	if (!form.value.comp1) return ''
	return binaryElements.value.find((el) => el !== form.value.comp1) || ''
})

// 三元相图可选元素
const ternaryElements = computed(() => {
	if (
		!form.value.firstElement ||
		!form.value.secondElement ||
		!form.value.thirdElement
	)
		return []
	return [
		form.value.firstElement,
		form.value.secondElement,
		form.value.thirdElement,
	]
})
const availableTernaryComp1Elements = computed(() =>
	ternaryElements.value.filter((el) => el !== form.value.comp2)
)
const availableTernaryComp2Elements = computed(() =>
	ternaryElements.value.filter((el) => el !== form.value.comp1)
)
const remainingTernaryElement = computed(() => {
	if (!form.value.comp1 || !form.value.comp2) return ''
	return (
		ternaryElements.value.find(
			(el) => el !== form.value.comp1 && el !== form.value.comp2
		) || ''
	)
})

// 元素选项
const elementOptions_computed = computed(() => {
	return isBinary.value ? elementOptions.binary : elementOptions.ternary
})

// 方法
const handleFirstElementChange = () => {
	form.value.secondElement = ''
	if (!isBinary.value) {
		form.value.thirdElement = ''
	}
	// 清空主动改变的元素选择
	form.value.comp1 = ''
	form.value.comp2 = ''
	form.value.comp3 = ''
}

const handleSecondElementChange = () => {
	if (!isBinary.value) {
		form.value.thirdElement = ''
	}
	// 清空主动改变的元素选择
	form.value.comp1 = ''
	form.value.comp2 = ''
	form.value.comp3 = ''
}

const resetForm = () => formRef.value?.resetFields()

const submitForm = async () => {
	if (!formRef.value) return
	try {
		await formRef.value.validate()

		// 构建符合API格式的数据
		let submitData = {}

		if (isBinary.value) {
			// 二元点图参数格式
			submitData = {
				tdb: currentTdbFile.value,
				elements: `${form.value.firstElement},${form.value.secondElement}`,
				temperature: form.value.temperature,
				pressure: form.value.pressure,
				comp1: form.value.comp1,
				comp1_value: form.value.comp1_value,
				// 二元情况下不需要comp2参数，第二个组分值自动为1-comp1_value
			}
		} else {
			// 三元点图参数格式
			submitData = {
				tdb: currentTdbFile.value,
				elements: `${form.value.firstElement},${form.value.secondElement},${form.value.thirdElement}`,
				temperature: form.value.temperature,
				pressure: form.value.pressure,
				comp1: form.value.comp1,
				comp1_value: form.value.comp1_value,
				comp2: form.value.comp2,
				comp2_value: form.value.comp2_value,
				// comp3: form.value.comp3,
				// comp3_value: form.value.comp3_value,
			}
		}

		emit('on-submit', { ...submitData, type: props.type, model: 'point' })
	} catch (error) {
		ElMessage.error('表单验证失败，请检查输入！')
	}
}

// 自动补全二元第二个元素
watch(
	() => [isBinary.value, form.value.firstElement],
	([isBin, first]) => {
		if (isBin && first) {
			const options = availableSecondElements.value
			if (options.length === 1) {
				form.value.secondElement = options[0]
			} else {
				form.value.secondElement = ''
			}
		}
	}
)

// 自动补全三元第三个元素
watch(
	() => [isBinary.value, form.value.firstElement, form.value.secondElement],
	([isBin, first, second]) => {
		if (!isBin && first && second) {
			const options = availableThirdElements.value
			if (options.length === 1) {
				form.value.thirdElement = options[0]
			} else {
				form.value.thirdElement = ''
			}
		}
	}
)

let isAutoFix = false

watch(
	() => [isBinary.value, form.value.comp1_value, form.value.comp2_value],
	([isBin, comp1, comp2], oldValue) => {
		const [prevIsBin, prevComp1, prevComp2] = oldValue || []
		if (isBinary.value) {
			form.value.comp2_value = Number((1 - Number(comp1)).toFixed(6))
		} else {
			if (isAutoFix) {
				isAutoFix = false
				return
			}
			let sum = Number(comp1) + Number(comp2)
			if (sum > 1) {
				isAutoFix = true
				if (comp2 !== prevComp2) {
					form.value.comp2_value = Number(
						Math.max(0, 1 - Number(comp1)).toFixed(6)
					)
				} else {
					form.value.comp1_value = Number(
						Math.max(0, 1 - Number(comp2)).toFixed(6)
					)
				}
				ElMessage.error('元素1和元素2成分值之和不能超过1，已自动修正')
			}
			const v =
				1 - Number(form.value.comp1_value) - Number(form.value.comp2_value)
			form.value.comp3_value = Number(Math.max(0, v).toFixed(6))
		}
	},
	{ immediate: true }
)
</script>

<template>
	<div class="left-middle">
		<el-form
			ref="formRef"
			:model="form"
			:rules="validationRules"
			label-width="0px"
			class="form"
		>
			<!-- 元素选择 -->
			<div class="section-row element-select-section-row">
				<div class="section-col">
					<div class="section-header">第一个元素</div>
					<el-form-item prop="firstElement">
						<el-select
							v-model="form.firstElement"
							class="section-select"
							@change="handleFirstElementChange"
							clearable
							placeholder="选择元素"
						>
							<el-option
								v-for="item in allElements"
								:key="item"
								:label="item"
								:value="item"
							/>
						</el-select>
					</el-form-item>
				</div>
				<div class="section-col">
					<div class="section-header">第二个元素</div>
					<el-form-item prop="secondElement">
						<el-select
							v-model="form.secondElement"
							class="section-select"
							@change="handleSecondElementChange"
							:disabled="!form.firstElement"
							clearable
							placeholder="选择元素"
						>
							<el-option
								v-for="item in availableSecondElements"
								:key="item"
								:label="item"
								:value="item"
							/>
						</el-select>
					</el-form-item>
				</div>
				<div v-if="!isBinary" class="section-col">
					<div class="section-header">第三个元素</div>
					<el-form-item prop="thirdElement">
						<el-select
							v-model="form.thirdElement"
							class="section-select"
							:disabled="!form.firstElement || !form.secondElement"
							clearable
							placeholder="选择元素"
						>
							<el-option
								v-for="item in availableThirdElements"
								:key="item"
								:label="item"
								:value="item"
							/>
						</el-select>
					</el-form-item>
				</div>
				<div class="section-col">
					<div class="section-header">对应数据库</div>
					<el-form-item>
						<el-input
							v-model="currentTdbFile"
							class="section-input"
							readonly
							disabled
						/>
					</el-form-item>
				</div>
			</div>

			<hr />

			<!-- 温度和压强 -->
			<div class="section-row tow-squares">
				<div class="section-col">
					<div class="section-header">温度</div>
					<div class="section-title">温度值 (K)</div>
					<el-form-item prop="temperature">
						<el-input
							v-model="form.temperature"
							v-positive-number
							class="section-input"
							placeholder="600"
						/>
					</el-form-item>
				</div>
				<div class="section-col">
					<div class="section-header">压强</div>
					<div class="section-title">压强值 (Pa)</div>
					<el-form-item prop="pressure">
						<el-input
							v-model="form.pressure"
							v-positive-number
							class="section-input"
							placeholder="101325"
						/>
					</el-form-item>
				</div>
			</div>

			<hr />

			<!-- 主动改变元素区域（仿照line.vue风格，灰色标题，三列布局） -->
			<div class="section-row">
				<div class="section-col">
					<div class="section-header">主动改变元素</div>
				</div>
			</div>
			<div
				:class="[
					isBinary
						? 'section-row element-select-section-row'
						: 'section-row three-squares',
				]"
			>
				<div class="section-col">
					<div class="section-title">元素1</div>
					<el-form-item prop="comp1">
						<el-select
							v-model="form.comp1"
							class="section-select"
							:disabled="
								isBinary
									? !form.firstElement || !form.secondElement
									: !form.firstElement ||
										!form.secondElement ||
										!form.thirdElement
							"
							clearable
							:placeholder="'请选择'"
						>
							<el-option
								v-for="el in isBinary
									? availableComp1Elements
									: availableTernaryComp1Elements"
								:key="el"
								:label="el"
								:value="el"
							/>
						</el-select>
					</el-form-item>
				</div>
				<div class="section-col">
					<div class="section-title">元素2</div>
					<el-form-item v-if="!isBinary" prop="comp2">
						<el-select
							v-model="form.comp2"
							class="section-select"
							:disabled="
								!form.firstElement || !form.secondElement || !form.thirdElement
							"
							clearable
							placeholder="请选择"
						>
							<el-option
								v-for="el in availableTernaryComp2Elements"
								:key="el"
								:label="el"
								:value="el"
							/>
						</el-select>
					</el-form-item>
					<el-form-item v-else>
						<el-input
							:value="remainingBinaryElement"
							class="section-input"
							readonly
							disabled
							placeholder="自动计算"
						/>
					</el-form-item>
				</div>
				<div class="section-col" v-if="!isBinary">
					<div class="section-title">元素3</div>
					<el-form-item>
						<el-input
							class="section-input"
							:value="remainingTernaryElement"
							readonly
							disabled
							placeholder="自动计算"
						/>
					</el-form-item>
				</div>
			</div>

			<hr />

			<!-- 元素1成分值 -->
			<div class="section-row">
				<div class="section-col">
					<div class="section-header">
						元素1成分值 ({{ form.comp1 || '元素1' }})
					</div>
				</div>
			</div>
			<div class="section-row tow-squares">
				<div class="section-col">
					<div class="section-title">成分值</div>
					<el-form-item prop="comp1_value">
						<el-input
							v-model="form.comp1_value"
							v-positive-number="{ maxDecimals: 3, min: 0, max: 1 }"
							class="section-input"
							step="0.01"
							placeholder="0.4"
						/>
					</el-form-item>
				</div>
				<div class="section-col">
					<div class="section-title">单位</div>
					<el-form-item prop="comp1_unit">
						<el-select v-model="form.comp1_unit" class="section-select">
							<el-option
								v-for="item in formConfig.units.composition"
								:key="item"
								:label="item"
								:value="item"
							/>
						</el-select>
					</el-form-item>
				</div>
			</div>

			<hr />

			<!-- 元素2成分值 -->
			<div class="section-row">
				<div class="section-col">
					<div class="section-header">
						元素2成分值 ({{
							isBinary
								? remainingBinaryElement || '元素2'
								: form.comp2 || '元素2'
						}})
						<span v-if="isBinary"> - 自动计算</span>
					</div>
				</div>
			</div>
			<div class="section-row tow-squares">
				<div class="section-col">
					<div class="section-title">成分值</div>
					<el-form-item :prop="isBinary ? undefined : 'comp2_value'">
						<el-input
							v-model="form.comp2_value"
							v-positive-number="{ maxDecimals: 3, min: 0, max: 1 }"
							class="section-input"
							step="0.01"
							:readonly="isBinary"
							:disabled="isBinary"
							:placeholder="
								isBinary ? (1 - form.comp1_value).toFixed(3) : '0.3'
							"
						/>
					</el-form-item>
				</div>
				<div class="section-col">
					<div class="section-title">单位</div>
					<el-form-item prop="comp2_unit">
						<el-select v-model="form.comp2_unit" class="section-select">
							<el-option
								v-for="item in formConfig.units.composition"
								:key="item"
								:label="item"
								:value="item"
							/>
						</el-select>
					</el-form-item>
				</div>
			</div>

			<!-- 三元时显示元素3成分值（自动计算） -->
			<template v-if="!isBinary">
				<hr />
				<div class="section-row">
					<div class="section-col">
						<div class="section-header">
							元素3成分值 ({{ remainingTernaryElement || '元素3' }}) - 自动计算
						</div>
					</div>
				</div>
				<div class="section-row tow-squares">
					<div class="section-col">
						<div class="section-title">成分值</div>
						<el-input
							v-model="form.comp3_value"
							class="section-input"
							readonly
							disabled
							:placeholder="
								(1 - form.comp1_value - form.comp2_value).toFixed(3)
							"
						/>
					</div>
					<div class="section-col">
						<div class="section-title">单位</div>
						<el-form-item prop="comp3_unit">
							<el-select v-model="form.comp3_unit" class="section-select">
								<el-option
									v-for="item in formConfig.units.composition"
									:key="item"
									:label="item"
									:value="item"
								/>
							</el-select>
						</el-form-item>
					</div>
				</div>
			</template>
		</el-form>
	</div>
	<div class="left-bottom">
		<el-button @click="resetForm">重置</el-button>
		<el-button color="black" :loading="props.isLoading" @click="submitForm">
			计算
		</el-button>
	</div>
</template>

<style scoped lang="scss">
@import url('./index.scss');
</style>
